package cn.phecda.boot.common.sensitive;

import cn.hutool.core.util.ReflectUtil;
import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.databind.JsonSerializer;
import com.fasterxml.jackson.databind.SerializerProvider;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;

import java.io.IOException;
import java.lang.reflect.Field;
import java.util.Objects;

/**
 * <p> 脱敏序列化 </p>
 *
 * @author : wanpinwei
 */
@Slf4j
public class SensitiveJacksonSerializer extends JsonSerializer<String> {

    @Override
    public void serialize(String fieldValue, JsonGenerator jsonGenerator, SerializerProvider serializerProvider) throws IOException {
        if (StringUtils.isBlank(fieldValue)) {
            jsonGenerator.writeString(fieldValue);
            return;
        }

        Object object = jsonGenerator.getCurrentValue();
        Class<?> objectClass = object.getClass();
        String fieldName = jsonGenerator.getOutputContext().getCurrentName();
        Field field = ReflectUtil.getField(objectClass, fieldName);
        Sensitive sensitive = field.getAnnotation(Sensitive.class);
        if (Objects.isNull(sensitive)) {
            jsonGenerator.writeString(fieldValue);
            return;
        }

        SensitiveStrategy strategy = sensitive.value();
        String finalValue = strategy.apply(new SensitiveMetaDataWrapper(object, objectClass, fieldName, fieldValue));
        if (log.isDebugEnabled()) {
            log.debug("|Phecda Boot Common Sensitive|- Sensitive for [{}={}] with {} strategy in {}",
                    fieldName, finalValue, strategy.name(), objectClass.getSimpleName());
        }

        jsonGenerator.writeString(finalValue);
    }

    @Override
    public Class<String> handledType() {
        return String.class;
    }
}
